#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <sys/wait.h>
#include <signal.h>
#include <pthread.h>

// 节点结构
typedef struct node
{
  int data;
  struct node* next;
}Node;
// 永远指向链表头部的指针
Node* head = NULL;


// 线程同步 互斥锁
pthread_mutex_t mutex;
// 线程阻塞
pthread_cond_t cond;

void* producer(void* arg)
{
  while(1)
  {
    // 创建一个链表的节点
    Node* pnew = (Node*)malloc(sizeof(Node));
    // 节点的初始化
    pnew->data = rand() % 1000;
    // 使用互斥锁保护数据
    pthread_mutex_lock(&mutex);
    pnew->next = head;
    head = pnew;
    printf("======producer: %lu, %d\n", pthread_self(), pnew->data);
    pthread_mutex_unlock(&mutex);
    pthread_cond_signal(&cond);

    sleep(rand() % 3);
  }
  return NULL;

}

void* comsumer(void* arg)
{
  while(1)
  {
    pthread_mutex_lock(&mutex);
    // 判断链表是否为空
    if(head == NULL)
    {
      // 线程阻塞
      // 该函数会对互斥锁解锁
      pthread_cond_wait(&cond, &mutex);
      // 解除阻塞之后，会对互斥锁枷锁操作
    }
    // 链表不为空， 删掉一个节点，删除头结点
    Node* pdel = head;
    head = head->next;
    printf("---------comsumer: %lu, %d\n", pthread_self(), pdel->data);
    free(pdel);
    pthread_mutex_unlock(&mutex);
  }
}

int main()
{
  pthread_t p1, p2;
  pthread_mutex_init(&mutex, NULL);
  pthread_cond_init(&cond, NULL);


  // 创建生产者线程
  pthread_create(&p1, NULL, producer, NULL);


  // 创建消费者线程
  pthread_create(&p2, NULL, comsumer, NULL);

  // 阻塞回收子线程
  pthread_join(p1, NULL);
  pthread_join(p2, NULL);
  pthread_mutex_destroy(&mutex);
  pthread_cond_destroy(&cond);
}
